package com.myproject.exception;

import com.myproject.datasource.context.DataSourceContextHolder;
import com.myproject.enums.ErrorCode;
import com.myproject.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@RestControllerAdvice
public class DataSourceExceptionHandler {
	// 数据源标识到业务名称的映射（避免硬编码）
	private static final Map<String, String> DS_NAME_MAP = Map.of("db1", "主数据库", "db2", "辅助数据库");

	// 处理SQL语法错误
	@ExceptionHandler(BadSqlGrammarException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<ErrorResponse> handleSqlException(BadSqlGrammarException e) {
		String dsKey = DataSourceContextHolder.getDataSource();
		String dsName = DS_NAME_MAP.getOrDefault(dsKey, "未知数据库");
		String traceId = UUID.randomUUID().toString();

		// 安全日志：脱敏敏感字段（如手机号、身份证号）
		String safeSql = e.getSql().replaceAll("\\b(\\d{3})\\d{4}(\\d{4})\\b", "$1****$2");
		log.error("[TraceID:{}] 数据源[{}] SQL错误: {}", traceId, dsName, safeSql, e);

		return Result.error(ErrorCode.SQL_ERROR, dsName + "执行失败，请稍后重试",
				Map.of("traceId", traceId, "dataSource", dsName, "safeSql", safeSql));
	}

	// 处理自定义业务异常
	@ExceptionHandler(BusinessException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<ErrorResponse> handleBusinessException(BusinessException e) {
		log.warn("业务异常: [{}] {}", e.getCode(), e.getMessage());
		return Result.error(e.getCode(), e.getMessage());
	}

	// 处理自定义系统异常
	@ExceptionHandler(SystemException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<ErrorResponse> handleSystemException(SystemException e) {
		String traceId = UUID.randomUUID().toString();
		log.error("[TraceID:{}] 系统异常: [{}] {}", traceId, e.getErrorCode().getCode(), e.getMessage(), e.getRootCause());

		return Result.error(e.getErrorCode(), "系统繁忙，请稍后再试", Map.of("traceId", traceId));
	}

	// 兜底异常处理
	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<ErrorResponse> handleGenericException(Exception e) {
		String traceId = UUID.randomUUID().toString();
		log.error("[TraceID:{}] 未处理异常: {}", traceId, e.getMessage(), e);
		return Result.error(ErrorCode.SYSTEM_ERROR, "系统内部错误", Map.of("traceId", traceId));
	}
}